import { Mesh, TextureLoader, LinearFilter, ShaderMaterial, Vector3, Vector2, FrontSide, ClampToEdgeWrapping } from 'three';
import Ellipsoid from '../math/Ellipsoid';
import EllipsoidGeometry from '../geometry/EllipsoidGeometry';
import Config from '../Config';

export default class EllipsoidMesh extends Mesh {
    private radius: Vector3;

    public constructor(center: Vector3 = new Vector3(0, 0, 0), radius: Vector3 = new Vector3(1, 0.99664, 1), widthSegments: number=32, heightSegments: number=16, texturePath: string = '/examples/resources/image/NE2_50M_SR_W_4096.jpg') {
        super();

        this.radius = radius;
        let ellipsoid: Ellipsoid = new Ellipsoid(center, radius);
        
        Config.EllipsoidConfig = {
            radius: radius,
            center: center,
        };
        Config.Ellipsoid = ellipsoid;
        Config.ellipsoidMesh = this;



        // 创建几何体
        this.geometry = new EllipsoidGeometry(radius, widthSegments, heightSegments);

        // 创建自定义着色器材质
        const customMaterial = new ShaderMaterial({
            uniforms: {
                oneOverRadiiSquared: {
                    value: ellipsoid.oneOverRadiiSquared,
                },
                map: {
                    value: null
                },
                ellipsoidCenter: {
                    value: Config.EllipsoidConfig.center.clone()
                },
                ellipsoidRadius: {
                    value: Config.EllipsoidConfig.radius.clone()
                },
                // 添加新的uniform变量
                gridResolution: {
                    // value: new Vector2(0.1, 0.1)
                    value: new Vector2(1, 1)
                },
                gridLineWidth: {
                    value: new Vector2(1.0, 1.0)
                }
            },
            vertexShader: `
                varying vec3 vPosition;

                void main() {
                    // 将顶点位置传递给片段着色器
                    vPosition = position.xyz;
                    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
                }
            `,
            fragmentShader: `
               //camera.matrixWorldInverse * object.matrixWorld
               uniform mat4 modelViewMatrix;

                //camera.projectionMatrix
                uniform mat4 projectionMatrix;

                uniform vec3 oneOverRadiiSquared;
                uniform sampler2D map;
                uniform vec2 gridResolution;
                uniform vec2 gridLineWidth;

                uniform vec3 ellipsoidCenter;
                uniform vec3 ellipsoidRadius;
                
                varying vec3 vPosition;

                // 计算射线与椭球的交点
                vec3 rayEllipsoidIntersection(vec3 rayOrigin, vec3 rayDirection, vec3 center, vec3 radii) {
                    // 移至椭球中心坐标系
                    vec3 origin = rayOrigin - center;
                    
                    // 归一化缩放因子
                    float scaleFactor = max(max(radii.x, radii.y), radii.z);
                    if (scaleFactor == 0.0) return vec3(0.0);
                    
                    // 归一化空间计算
                    vec3 normalizedOrigin = origin / scaleFactor;
                    vec3 normalizedDirection = normalize(rayDirection);
                    vec3 normalizedRadii = radii / scaleFactor;
                    vec3 normalizedOneOverRadiiSquared = vec3(
                        1.0 / (normalizedRadii.x * normalizedRadii.x),
                        1.0 / (normalizedRadii.y * normalizedRadii.y),
                        1.0 / (normalizedRadii.z * normalizedRadii.z)
                    );
                    
                    // 计算二次方程系数
                    float A = dot(normalizedDirection * normalizedOneOverRadiiSquared, normalizedDirection);
                    
                    // 添加小的epsilon避免除零错误
                    const float EPSILON = 1e-12;
                    if (abs(A) < EPSILON) return vec3(0.0); // 射线方向几乎与椭球无交线
                    
                    float B = 2.0 * dot(normalizedOrigin * normalizedOneOverRadiiSquared, normalizedDirection);
                    float C = dot(normalizedOrigin * normalizedOneOverRadiiSquared, normalizedOrigin) - 1.0;
                    
                    // 判别式
                    float discriminant = B * B - 4.0 * A * C;
                    const float DISCRIMINANT_EPSILON = 1e-10;
                    
                    if (discriminant < -DISCRIMINANT_EPSILON) return vec3(0.0); // 无交点
                    
                    // 调整判别式，避免浮点精度问题
                    discriminant = max(discriminant, 0.0);
                    float sqrtDiscriminant = sqrt(discriminant);
                    
                    float t1 = (-B - sqrtDiscriminant) / (2.0 * A);
                    float t2 = (-B + sqrtDiscriminant) / (2.0 * A);
                    
                    // 找出有效的交点参数（大于等于0）
                    float validT = -1.0;
                    if (t1 >= 0.0 && t2 >= 0.0) {
                        // 如果两个交点都有效，选择较远的点作为背面交点
                        validT = max(t1, t2);
                    } else if (t1 >= 0.0) {
                        validT = t1;
                    } else if (t2 >= 0.0) {
                        validT = t2;
                    }
                    
                    // 添加有效值检查，避免极端情况
                    if (validT < 0.0 || validT > 1e10) return vec3(0.0); // 无有效交点或交点过远
                    
                    // 计算交点
                    vec3 normalizedIntersection = normalizedOrigin + normalizedDirection * validT;
                    vec3 intersection = normalizedIntersection * scaleFactor + center;
                    
                    return intersection;
                }

                float computeWorldPositionDepth(vec3 position, mat4 mvpMatrix){ 
                    vec4 v = mvpMatrix * vec4(position, 1.0);  
                    v.z = v.z / v.w;                           
                    v.z = (v.z + 1.0) * 0.5;
                    return v.z;
                }

                void computeNewDepth(){
                 // cameraPosition 是Three.js内置变量, 表示相机世界坐标
                    vec3 rayOrigin = cameraPosition;
                    vec3 rayDirection = normalize(vPosition - cameraPosition);

                    // 计算射线与椭球背面的交点
                    vec3 backIntersection = rayEllipsoidIntersection(rayOrigin, rayDirection, ellipsoidCenter, ellipsoidRadius);
                    vec3 middlePoint =  (vPosition + backIntersection)/2.0; //计算椭球前面的点和背面点中间的坐标
                    gl_FragDepth = computeWorldPositionDepth(middlePoint, projectionMatrix * modelViewMatrix);//重新计算深度值
                }

                vec2 adjustUV(vec2 uv){
                    vec2 edge = vec2(1.0, 1.0);
                    vec2 modValue = mod(uv, vec2(1.0, 1.0));
                    vec2 dx = abs(dFdx(uv));
                    vec2 dy = abs(dFdy(uv));
                    vec2 dF = vec2(max(dx.s, dy.s), max(dx.t, dy.t) * vec2(1.0, 1.0));
                    if(any(lessThan(modValue, dF))) {
                        uv.s = 0.0;
                    }
                    return vec2(uv.s, uv.t);
                }

                void main() {
                    // 在片段着色器中计算地心法线
                    vec3 normal = vPosition * oneOverRadiiSquared;
                    normal = normalize(normal);

                    // 使用法线计算纹理坐标
                    float s = atan(normal.y, normal.x) / (2.0 * 3.141592653589793) + 0.5;
                    float t = asin(normal.z) / 3.141592653589793 + 0.5;
                    vec2 uv = vec2(s, t);

                    // vec2 distanceToLine = mod(uv, gridResolution);
                    // vec2 dx = abs(dFdx(uv));
                    // vec2 dy = abs(dFdy(uv));
                    // vec2 dF = vec2(max(dx.s, dy.s), max(dx.t, dy.t) * gridLineWidth);
                    // if(any(lessThan(distanceToLine, dF))) {
                    //     // gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
                    //     uv.s = 0.0;
                    //     vec4 color = texture2D(map, uv);
                    //     gl_FragColor = color;
                    // } else {
                        // uv = adjustUV(vec2(uv.s, uv.t));
                        // 使用计算出的纹理坐标采样纹理
                        vec4 color = texture2D(map, uv);
                        gl_FragColor = color;
                    // }

                    computeNewDepth();
                }
            `
        });

        // 加载纹理
        const textureLoader = new TextureLoader();
        const texture = textureLoader.load(texturePath, () => {
            texture.minFilter = LinearFilter; // 使用带mipmap的过滤方式
            texture.magFilter = LinearFilter;
            texture.wrapS = ClampToEdgeWrapping;
            texture.wrapT = ClampToEdgeWrapping;
            texture.generateMipmaps = true; // 启用mipmap生成
            customMaterial.uniforms.map = { value: texture };
            customMaterial.needsUpdate = true;
        });

        customMaterial.side = FrontSide;
        customMaterial.depthTest = true;
        customMaterial.needsUpdate = true;

        // 设置材质
        this.material = customMaterial;

        // this.rotation.x = -Math.PI / 2;
    }

    // 添加外部设置方法
    public setGridResolution(resolution: Vector2): void {
        (this.material as ShaderMaterial).uniforms.gridResolution.value = resolution;
    }

    public setGridLineWidth(width: Vector2): void {
        (this.material as ShaderMaterial).uniforms.gridLineWidth.value = width;
    }
}